package server;

import java.util.ArrayList;
import util.ArrayHelpers;
import util.Logger;
import client.ClientDirectory;
import client.ClientFile;
import dataContracts.Command;
import dataContracts.FileStatus;
import dataContracts.SharedFile;

public class SynchHandler implements Runnable {
	ClientConnection client;
	ServerProgram server;
	Command command;
	
	SynchHandler(ClientConnection client, ServerProgram server, Command cmd) {
		this.server = server;
		this.client = client;
		this.command = cmd;
	}
	
	@Override
	public void run() {
		// keep track of changes we need to make
		ArrayList<String> added, deleted, changed;
		added = new ArrayList<String>();
		deleted = new ArrayList<String>();
		changed = new ArrayList<String>();
		
		Logger.Debug("Client Directory Checksum: "+ command.directoryInfo.getChecksum());
		
		// assume all files on server are new, and we'll remove them from the list as needed
		for (SharedFile file : server.directory.files) {
			added.add(file.getName());
		}
		
		//loop through the list of files sent
		for (SharedFile file : command.directoryInfo.files) {
			String name;
			name = file.getName();
			SharedFile serverMatch = server.directory.findFile(name);
			
			if (serverMatch != null) {
				added.remove(name);
				// file exists on server
				if (file.status == FileStatus.Deleted) {
					deleted.add(name);
					Logger.Debug("Asking to Delete: "+ file.getName());
					server.directory.deleteFile(serverMatch.getName());
					client.command(Command.Type.DeleteFile, name);
				} else {
					if (!serverMatch.equals(file)) {
						// TODO synch the attributes on the object
						Logger.Debug("Synch Attributes for: "+ name + " in project "+ file.getProject());
						Logger.Debug("\t "+ file.checksum + "\t "+ serverMatch.getChecksum() + "\n");
						Logger.Debug("client vs server timestamps: "+ file.lastModified +" vs "+ serverMatch.lastModified);
						if (file.lastModified < serverMatch.lastModified) {
							// server has newer version
							Command syncAtClient = new Command(Command.Type.SyncAttributes, name);
							syncAtClient.directoryInfo = server.directory;
							server.commandAllClients(syncAtClient);
						} else if (file.lastModified > serverMatch.lastModified) {
							// client has newer version, update the metadata here
							server.directory.copyMetaData(serverMatch, file);
							Command syncAtClient = new Command(Command.Type.SyncAttributes, name);
							syncAtClient.directoryInfo = server.directory;
							server.commandAllClients(syncAtClient);
						} else {
							Logger.Debug("Last update was identical");
						}
						
						// send all the attributes down the wire
//						Command cmd = new Command(Command.Type.SyncAttributes, file.getName());
//						cmd.directoryInfo = server.directory;
//						client.command(cmd);
						
						// if the file itself changed, kick off the download/upload process
						if (!serverMatch.equalOnDisk(file)) {
							changed.add(name);
							if (file.lastModified < serverMatch.lastModified) {
								// server has newer version
								client.command(Command.Type.UpdateFile, name);
							} else {
								// client has newer version, ask it to upload
								client.command(Command.Type.UploadFile, name);
							}
						}
						
					} else {
						client.command(Command.Type.MarkAsCurrent, name);
						Logger.Debug("Current!");
					}
				}
			} else {
				// we can't tell if it's new on client, or deleted on server... make client resolve
				client.command(Command.Type.ResolveDiff, name);
				deleted.add(name);
				added.remove(name);
			}
		}
		
		// for all the actual new files, trigger the download
		for (String fileAdded : added) {
			client.command(Command.Type.NewFile, fileAdded);
		}
	}
}